package org.eliza.base.coroutinesx.flow

//冷流 🥶
//冷指的是 无消费者时 则不会生产数据
//热流 🥵
//热指的是 无观察者时 也会生产数据


/*
StateFlow
有状态的Flow ，可以有多个观察者，热流
    构造时需要传入初始值 : initialState
    常用作与UI相关的数据观察，类比LiveData

SharedFlow
    可定制化的StateFlow，可以有多个观察者，热流. 无需初始值，有三个可选参数：
    replay - 重播给新订阅者的值的数量（不能为负，默认为零）。
    extraBufferCapacity - 除了replay之外缓冲的值的数量。 当有剩余缓冲区空间时， emit不会挂起（可选，不能为负，默认为零）。
    onBufferOverflow - 配置缓冲区溢出的操作（可选，默认为暂停尝试发出值）


 */

/*
* 中间操作符
    一般来说是用来执行一些操作，不会立即执行，返回值还是个Flow
末端操作符
    会触发流的执行，返回值不是Flow
*
* flow{}.map{}.filter{}.take().
*
*创建Flow的基本方法.
使用 emit 发射单个值
使用 emitAll 发射一个流 ，类似 list.addAll(anotherList)
*
 */

/*
* Create
* callbackFlow
    将回调方法改造成flow ,类似suspendCoroutine
*
* channelFlow
    在一般的flow在构造代码块中不允许切换线程，ChannelFlow则允许内部切换线程
*
*末端操作符
*
*   collect           //触发flow的运行
*   collectIndexed    //带下标
*   collectLatest
        与 collect的区别是 ，有新值发出时，如果此时上个收集尚未完成，则会取消掉上个值的收集操作
*   toCollection 将结果添加到集合
*
*   launchIn  //返回job，直接触发流的执行，不设置action,入参为coroutineScope 一般不会直接调用，会搭配别的操作符一起使用
*   first 第一个值 ,如果为空会抛异常
*   last 最后一个值 ,如果为空会抛异常
*   single 接收流发送的第一个值 ，区别于first(),如果为空或者发了不止一个值，则都会报错
*   count  类似list.size() ，注：sharedFlow无效(无意义）
*   filter  筛选出符合条件的值
*   filterNot  filter取反
*   drop  ,作用是 丢弃掉前 n 个的值
*   dropWhile 它是找到第一个不满足条件的，返回其和其之后的值。如果首项就不满足条件，则是全部返回
*   take 返回前 n个 元素
*   debounce 指定时间内的值只接收最新的一个，其他的过滤掉
*   sample 给定一个时间周期，仅获取周期内最新发出的值
*   distinctUntilChangedBy 判断连续的两个值是否重复，可以选择是否丢弃重复值。
*   distinctUntilChanged 。连续两个值一样，则跳过发送
*
*   combine 。组合每个流最新发出的值。
*   merge 。合并多个流成 一个流。 可以用在 多级缓存加载上。
*   flattenConcat  以顺序方式将给定的流展开为单个流 ，是Flow<Flow<T>>的扩展函数
*   flattenMerge   flattenConcat 一样，但是可以设置并发收集流的数量。concurrency: Int ,当其 == 1时，效果和 flattenConcat 一样，大于 1 时，则是并发收集。
*   zip   对两个流进行组合，分别从二者取值，一旦一个流结束了，那整个过程就结束了。
*
*   catch   对上游(操作符之前的流)异常进行捕获 ，对下游无影响
*   retryWhen   lambda 中有两个参数: 一个是 异常原因，一个是当前重试的 index (从0开始).
*   buffer   在执行期间为其创建一个单独的协程, SUSPEND 挂起， DROP_OLDEST 丢掉旧的，DROP_LATEST 丢掉新的
*   flowOn  切换执行线程
*
*
*
*
*   fold  从初始值开始 执行遍历,并将结果作为下个执行的 参数。
*   reduce 和fold 差不多。 无初始值
*   scan    和 fold 相似，区别是fold 返回的是最终结果，scan返回的是个flow ，会把初始值和每一步的操作结果发送出去。
*   runningFold  区别于 fold ，就是返回一个新流，将每步的结果发射出去。
*   runningReduce  区别于 reduce ，就是返回一个新流，将每步的结果发射出去。
*
* map 将发出的值 进行变换 ，lambda的返回值为最终发送的值
* mapLatest 类比 collectLatest ,当有新值发送时如果上个变换还没结束，会先取消掉
* transform 区别于map， transform的接收者是FlowCollector ，因此它非常灵活，可以变换、跳过它或多次发送。
* transformWhile lambda 的返回值是 Boolean ,如果为 False则不再进行后续变换, 为 True则继续执行
*
* asStateFlow 将 MutableStateFlow 转换为 StateFlow ，就是变成不可变的。常用在对外暴露属性时使用
* receiveAsFlow 将Channel 转换为Flow ,可以有多个观察者，但不是多播，可能会轮流收到值。
* consumeAsFlow 将Channel 转换为Flow ,但不能多个观察者（会crash）!
*
*
*
* * */


/*
* shareIn
* 将普通flow 转化为 SharedFlow , 其有三个参数
    scope: CoroutineScope 开始共享的协程范围 started: SharingStarted 控制何时开始和停止共享的策略
    replay: Int = 0 发给 新的订阅者 的旧值数量
*
* 其中 started 有一些可选项:
    Eagerly : 共享立即开始，永不停止
    Lazily : 当第一个订阅者出现时,永不停止
    WhileSubscribed : 在第一个订阅者出现时开始共享，在最后一个订阅者消失时立即停止（默认情况下），永久保留重播缓存（默认情况下）
    WhileSubscribed 具有以下可选参数：
    stopTimeoutMillis — 配置最后一个订阅者消失到协程停止共享之间的延迟（以毫秒为单位）。 默认为零（立即停止）。
    replayExpirationMillis - 共享的协程从停止到重新激活，这期间缓存的时效
*
* stateIn
* 将普通flow 转化为 StateFlow 。 其有三个参数：
    scope - 开始共享的协程范围
    started - 控制何时开始和停止共享的策略
    initialValue - 状态流的初始值
*
* */